package com.jfinal.plugin.activerecord;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

public abstract class BatchModel<M extends Model> extends Model{
	public void batchSave(List<M> beanList) {
		if (beanList != null && beanList.size() > 0) {
			Config config = DbKit.getConfig(getClass());
			com.jfinal.plugin.activerecord.Table table = TableMapping.me().getTable(getClass());

			try {
				String sql = null;
				List<Object[]> paramsList = new ArrayList<Object[]>();
				for (M bean : beanList) {
					StringBuilder sb = new StringBuilder();
					List<Object> paras = new ArrayList<Object>();
					config.getDialect().forModelSave(table, bean.getAttrs(), sb, paras);
					if (sql == null) {
						sql = sb.toString();
					}
					paramsList.add(paras.toArray());
				}
				Object[][] paramss = new Object[paramsList.size()][];
				int i = 0;
				for (Object[] oo : paramsList) {
					paramss[i++] = oo;
				}

				batchExecUpdate(sql, paramss);
			} catch (Exception e) {
				throw new ActiveRecordException(e);
			}
		}
	}

	private int[] batchExecUpdate(String sql, Object[]... paramss) throws SQLException {
		Config config = DbKit.getConfig(getClass());
		com.jfinal.plugin.activerecord.Table table = TableMapping.me().getTable(getClass());

		if (paramss == null) {
			paramss = new Object[0][0];
		}
		Connection conn = null;
		PreparedStatement pst = null;
		int[] rows = null;
		try {
			conn = config.getConnection();
			if (config.getDialect().isOracle()) {
				pst = conn.prepareStatement(sql.toString(), new String[] { table.getPrimaryKey() });
			} else {
				pst = conn.prepareStatement(sql.toString(), Statement.RETURN_GENERATED_KEYS);
			}
			for (Object[] params : paramss) {
				config.getDialect().fillStatement(pst, params);
				pst.addBatch();
			}
			rows = pst.executeBatch();
		} finally {
			config.close(pst, conn);
		}
		return rows;
	}
}
